﻿using IM.Easy.Entity.System;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace EndpointManagement
{
    /// <summary>
    /// 提供端点的注册、查询和管理功能的静态类。
    /// </summary>
    public static class EndPointManager
    {
        private static readonly Dictionary<string, ApiPermissions> _endpoints = [];

        /// <summary>
        /// 注册一个端点。
        /// </summary>
        /// <param name="key">端点的键，必须唯一。</param>
        /// <param name="url">端点的URL。</param>
        /// <exception cref="ArgumentException">如果键或URL为空或仅包含空白字符。</exception>
        public static void Register(string key, ApiPermissions url)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("键不能为空或仅包含空白字符。", nameof(key));
            _endpoints[key] = url ?? throw new ArgumentException("URL 不能为空或仅包含空白字符。", nameof(url));
        }

        /// <summary>
        /// 注册一个端点。同时返回主键
        /// </summary>
        /// <param name="url">端点的URL。</param>
        /// <exception cref="ArgumentException">如果键或URL为空或仅包含空白字符。</exception>
        public static string Register(ApiPermissions url)
        {
            var key = $"{url.Path}:{url.HttpMethod}";
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("键不能为空或仅包含空白字符。", nameof(key));
            _endpoints[key] = url ?? throw new ArgumentException("URL 不能为空或仅包含空白字符。", nameof(url));
            return key;
        }

        /// <summary>
        /// 批量注册多个端点
        /// </summary>
        /// <param name="urls"></param>
        public static void Register(List<ApiPermissions> urls)
        {
            foreach (var item in urls)
            {
                Register(item);
            }
        }

        /// <summary>
        /// 获取指定键的端点URL。   routePattern：method 格式
        /// </summary>
        /// <param name="key">要查询的端点键。</param>
        /// <returns>与键对应的端点URL。</returns>
        /// <exception cref="ArgumentException">如果键为空或仅包含空白字符。</exception>
        /// <exception cref="KeyNotFoundException">如果指定的键未注册。</exception>
        public static ApiPermissions Get(string key, bool throwNull = false)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("键不能为空或仅包含空白字符。", nameof(key));

            var flag = _endpoints.TryGetValue(key, out var url);
            if (throwNull && !flag) throw new KeyNotFoundException($"未找到键为 '{key}' 的端点。");
            return url;
        }

        /// <summary>
        /// 检查指定的端点键是否已注册。
        /// </summary>
        /// <param name="key">要检查的端点键。</param>
        /// <returns>如果已注册返回 true，否则返回 false。</returns>
        /// <exception cref="ArgumentException">如果键为空或仅包含空白字符。</exception>
        public static bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("键不能为空或仅包含空白字符。", nameof(key));

            return _endpoints.ContainsKey(key);
        }

        /// <summary>
        /// 取消注册指定键的端点。
        /// </summary>
        /// <param name="key">要取消注册的端点键。</param>
        /// <exception cref="ArgumentException">如果键为空或仅包含空白字符。</exception>
        /// <exception cref="KeyNotFoundException">如果指定的键未注册。</exception>
        public static void Unregister(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("键不能为空或仅包含空白字符。", nameof(key));

            if (!_endpoints.Remove(key))
            {
                throw new KeyNotFoundException($"未找到键为 '{key}' 的端点，无法删除。");
            }
        }

        /// <summary>
        /// 更新一个已注册的端点。
        /// </summary>
        /// <param name="key">端点的键，必须唯一。</param>
        /// <param name="url">新的端点URL。</param>
        /// <exception cref="KeyNotFoundException">如果指定的键不存在。</exception>
        /// <exception cref="ArgumentException">如果键或URL为空或仅包含空白字符。</exception>
        public static void Update(string key, ApiPermissions url)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentException("键不能为空或仅包含空白字符。", nameof(key));

            if (!_endpoints.ContainsKey(key))
                throw new KeyNotFoundException($"指定的键 '{key}' 不存在，无法更新。");

            _endpoints[key] = url ?? throw new ArgumentException("URL 不能为空或仅包含空白字符。", nameof(url));
        }

        public static void UpdateOrAdd(ApiPermissions url)
        {
            var key = $"{url.Path}:{url.HttpMethod}";
            if (Exists(key))
            {
                Update(key, url);
            }
            else
            {
                Register(url);
            }
        }


        /// <summary>
        /// 获取所有已注册的端点键值对。
        /// </summary>
        /// <returns>只读字典，包含所有已注册的端点。</returns>
        public static IReadOnlyDictionary<string, ApiPermissions> GetAll()
        {
            return new ReadOnlyDictionary<string, ApiPermissions>(_endpoints);
        }

        /// <summary>
        /// 清除所有
        /// </summary>
        public static void Clear()
        {
            _endpoints.Clear();
        }
    }
}
